
/*-------------------------------------------------------------------------

***************** Modification History ***********************************
   @doc
   @module batch.c - API functions for Batch File Maintenance |
   @end

$Log: /SoftPay/SPK2SIM/Source/Batch/batch.c $
**************************************************************************

   Copyright (C) 1999 by VeriFone, Inc.

   All rights reserved.  No part of this software may be reproduced,
   transmitted, transcribed, stored in a retrieval system, or translated
   into any language or computer language, in any form or by any means,
   electronic, mechanical, magnetic, optical, chemical, manual or otherwise,
   without the prior written permission of VeriFone, Inc.

---------------------------------------------------------------------------*/

#include <project.h>

#ifdef BATCH_DEFINED

#define VSBATCH_C

#include <aclconio.h>
#include <stdlib.h>
#include <stdio.h>
#include <ascii.h>
#include <errno.h>
#include <svc.h>
#include <dbmgr.h>
#include <string.h>
#include <message.h>
#include <aclstr.h>
#include <aclutil.h>
#include <VarRec.h>


/** /#define DEBUG_VSBATCH*/
#ifdef DEBUG_VSBATCH
#define DEBUG_95
#endif

#include <define.h>
#include <transact.h>
#include <tran.h>
#include <util.h>
#include <mem.h>
#include <gds.h>
#include <msg.h>
#include <msgfuncs.h>
#include <msgclrk.h>
#include <msgshf.h>
#include <cdt.h>
#include <cst.h>
#include <hdt.h>
#include <bdt.h>
#include <opt.h>
#include <tct.h>
#include <trt.h>
#include <sdt.h>
#include <confio.h>
#include <form.h>
#include <revutl.h>
#include <test.h>
#include <spdebug.h>
#include <ui.h>
#include <entry.h>
#include <operate.h>
#include <pbatch.h>
#include <mdlfuncs.h>
#include <accum.h>
#include <table.h>
#include <funcids.h>
#include <autosttl.h>
#include <settle.h>
#include <settlbat.h>
#include <review.h>
#include <batmsg.h>
#include <mht.h>
#include <pfr.h>
#include <codesec.h>
#include <logo.h>
#include <mit.h>
#include <merch.h>
#include <multilng.h>
#include <oper.h>
#include <date.h>
#include <tblutil.h>

FUNCTION_TABLE srBatchFuncs[] = {
    {inUserChoice,                          USER_CHOICE},
    {inSettleUnadjustTips,                  SETTLE_UNADJUST_TIPS},
    {inGetInvBatchRec,                      GET_INV_BATCH_REC},
    {inValidateVoid,                        VALIDATE_VOID},
    {inValidateAdjust,                      VALIDATE_ADJUST},
    {inConfirmInvAmt,                       CONFIRM_INV_AMT},
    {inVoidBatchRec,                        VOID_BATCH_REC},
    {inAdjustBatchRec,                      ADJUST_BATCH_REC},
    {inUpdateBatchFlow,                     UPDATE_BATCH},
    {inSameCardConfirm,                     CONFIRM_SAME_CARD},
    {inDeleteOpenTab,                       DELETE_OPEN_TAB},
    {inValidateTipAdjust,                   VALIDATE_TIP_ADJUST},
    {inBatchReviewTipAdjust,                BATCH_REVIEW_TIP_ADJUST},
    {inRetrieveInvOrAcct,                   GET_INV_OR_ACCT_NUM},
    {inOpenDCBatch,                         OPEN_DC_BATCH},
    {inOpenTabBatch,                        OPEN_TAB_BATCH},
    {inDetailReportOperation,               PRINT_DETAIL_REPORT},
    {inReprintAnyReceiptOperation,          REPRINT_ANY_RECEIPT},
    {inReprintLastReceiptOperation,         REPRINT_LAST_RECEIPT},
    {inSummaryReviewOperation,              REVIEW_BATCH_REPORT},
    {inOpenTabReportOperation,              PRINT_OPENTAB_REPORT},
    {inTipReviewOperation,                  BATCH_TIP_REVIEW},
    {inIdleAutoSettle,                      IDLE_AUTO_SETTLE},
    {inBatchClearOperation,                 BATCH_CLEAR_OPERATION},
    {inInitPurgeHostFromBatch,              PURGE_HOST_INIT},
    {inReprintSettlementReportOperation,    REPRINT_SETTLEMENT},
    {inSettleOperation,                     SETTLEMENT},
    {inRePrintSettlementReport,             REPRINT_STL_REPORT},
    {inPrintSettleReport,                   PRINT_SETTLE_REPORT},
    {inDefaultUpdateBatchForVoid,           UPDATE_BATCH_FOR_VOID},
    {inDefaultUpdateBatchForAdjust,         UPDATE_BATCH_FOR_ADJUST},
    {inDefaultUpdateBatchForVoidAndAdjust,  UPDATE_BATCH_FOR_VOID_AND_ADJUST},
    {inDefaultIsVoidTransaction,            IS_VOID_TRANSACTION},
    {inVoidChoice,                          VOID_CHOICE},
    {0,                                     END_OF_FUNC_TABLE},

};

/*********************************************************************************************
* @func int | inAddBatchFunctions |
*
*       Adds BATCH functions to the flexi record.
*
* @rdesc Return values.
*
* @flag int    |    - VS_ERR
*                   - VS_SUCCESS
* @end
**********************************************************************************************/

int inAddBatchFunctions(void) {
    int inCount = 0;

    /* Add batch overloadable functions to the Flexi Record */
    do {
        if (inAddFunctionPointer(srBatchFuncs[inCount].inFieldID, srBatchFuncs[inCount].pinFunction) == VS_ERR)
            return (VS_ERR);
        inCount++;
    } while (srBatchFuncs[inCount].inFieldID != END_OF_FUNC_TABLE);

    return(VS_SUCCESS);
}


/*********************************************************************************************
* @func int | inClearBatch |
*
*       Delete all the batch records after the batch close transaction.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm int     | inClearType |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inClearBatch(TRANSACTION_OBJECT* pobTran,int inClearType,VS_BOOL fDisplayFlag) {
    char pchBFName[FILENAME_SIZE + 1];
    int inHostNum;
    int inResult;
    DB_FILE dbReprintFile;


    /** /pdebug(("--inClearBatch--"));*/

    /*
     *      Reset Data Capture Batch
     */
    if (inClearType == CLEAR_BATCH) {
        vdCloseDCBatch(pobTran);
        vdGetBatchFName(pchBFName);
        if ((inResult = db_open(&pobTran->dbBatch, pchBFName, SIZE_BATCH_KEY, (O_TRUNC | O_CREAT | O_RDWR))) < 0) {
            /**/pdebug(("Batch Clear Open Failed (%s/%d/%d)", pchBFName, inResult, errno));/**/
            return(VS_ERR);
        }
        vdResetMaxBatchRecSize();
        pobTran->fBatchOpen = VS_TRUE;
        vdCloseDCBatch(pobTran);
        for (inHostNum = 0; inHostNum < MAX_HOSTS; ++inHostNum) {
            /** /pdebug (("Host Rec %d+1 of %d.",inHostNum,MAX_HOSTS));*/
            /** /pdebug (("inGetMITMerchantNum()=%d",inGetMITMerchantNum()));*/
            /* load temporary HDT and MHT, so the accum files will get cleared,
                otherwise the accum files won't get cleared properly */

            if (inLoadMHTRec(inHostNum) != VS_SUCCESS) {
                vdSGErrorMessage(MHT_ERR_MSG21); /* MHT_ERR_MSG */
                return(VS_ERR);
            }
            vdSetMustClear(VS_FALSE);
            vdSetMustSettleFlag(VS_FALSE);
            if (inSaveMHTRec(inHostNum) != VS_SUCCESS) {
                vdSGErrorMessage(MHT_ERR_MSG21);
                return(VS_ERR);
            }


            inLoadHDTRec(inHostNum);
            /* reset accum file for each host */
            if (inResetAccum() != VS_SUCCESS)
                vdDisplayMessageFromFile(ACCUM_FAIL_ERR_MSG, ERROR_MSG);

            /* Remove the reversal and offline files for each host if exist */
            vdReversalsDelete(inHostNum);
        }
        /*
         *      Reset invoice number
         */
        if ((inResult = inResetInvNum()) != VS_SUCCESS)
            vdDisplayMessageFromFile(BDT_ERR_MSG, ERROR_MSG);
    } else if (inClearType == CLEAR_HOST)
        inPurgeHostFromBatch(pobTran, inGetBatchIndex(), fDisplayFlag);
    else {
        vdSGErrorMessage(BAT_REMOVE_FAIL_ERR_MSG);
        return(VS_ERR);
    }

    /*
     *       delete reprint receipt file
     */
    if (db_open(&dbReprintFile, REPRINT_FILE_NAME, SIZE_BATCH_KEY, (O_TRUNC | O_CREAT | O_RDWR)) < 0)
        return(VS_ERR);

    db_delete(&dbReprintFile, 0L, 1L) ;

    if (inCloseBatch(&dbReprintFile) != VS_SUCCESS)
    {

        vdSGErrorMessage(BATCH_ERR_MSG);
	}
    /*
     *      Delete Last Data Entry file.
     */
    vdGetDupChkFName(pchBFName);

    if (inChkFileExist(pchBFName) == VS_SUCCESS)
        remove(pchBFName);

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func static int | inAddBatchRec |
*
*       Adds record to the batch.
*       NOTE:   The Open Tab batch is used if it is open, otherwise the
*               Data Capture batch is used.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm long    | lnRecNum |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/
static int inAddBatchRec(TRANSACTION_OBJECT* pobTran,BATCH_KEY* psrBKey,BATCH_REC* psrBRec,long lnRecNum) {
    long lnDBWhat = lnRecNum;
    DB_FILE* psrDBF;

    pdebug(("--inAddBatchRec--"));


    // Load new batch record field
    pobTran->srBRec.inMerchantIndex = inGetMITIndex();

    /*
     *      Add to the Open Tab batch if it is available, otherwise operate on the Primary Batch
     */
    if (pobTran->fOTBatchOpen) {
        /** /pdebug (("Add Tab"));*/
        psrDBF = &pobTran->dbOTBatch;
    } else {
        /** /pdebug (("Add Record"));*/
        psrDBF = &pobTran->dbBatch;
    }


    if (lnRecNum == DB_CURRENT)
        lnDBWhat = ((psrDBF->kfile.curr_rec_num <= 0L) ? 0L : (psrDBF->kfile.curr_rec_num - 1));

    if (inWriteBatchData(psrDBF, psrBKey, psrBRec, lnDBWhat) != VS_SUCCESS) {


        vdSGErrorMessage(BATCH_ERR_MSG);
        return(VS_ERR);
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inPutBatchRec |
*
*       Forms the batch record from the gds data, puts it to the appropriate
*       batch file.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inPutBatchRec(TRANSACTION_OBJECT* pobTran) {
    char szPAN[PAN_SIZE + 1];
    int inResult;

    /** /pdebug (("--inPutBatchRec--"));*/

    /* Save Original Tran Code */
    pobTran->srBRec.inOrgCode = inGGCode();

    /* Save Original Inv Num */
    /* Save original STAN */
    if (!pobTran->srBRec.fCloseTabSameCard && !pobTran->fReferral)
        pobTran->srBKey.lnOrgSTAN = pobTran->srBRec.lnSTAN;
    if (!pobTran->srBRec.fCloseTabSameCard)
        pobTran->srBRec.lnOrgInvNum = pobTran->srBKey.lnInvNum;

    /* Set Batch Link variables */
    pobTran->srBRec.lnForwardLinkInvNum = 0L;
    pobTran->srBRec.lnBackLinkInvNum = 0L;
    pobTran->srBRec.fDoNotUploadRec = VS_FALSE;
    pobTran->srBRec.fLastTranUploaded = VS_FALSE;



    /* Save Currency Index */
    pobTran->srBKey.inCurrencyIndex = shGetCurrencyIndex();

    /* If datacapture flag is not set don't store in the batch */

    if ((fGetDataCapture(pobTran) != VS_TRUE) && (!pobTran->srBRec.fCloseTabSameCard && !pobTran->srBRec.fCloseTabNewCard) && (inGGCode() != OPENTAB_DEL))
        return(VS_SUCCESS);

    /* Form the batch record */
    /** /pdebug (("--form batch rec--"));*/
    if (pobTran->srBRec.fCloseTabSameCard || pobTran->srBRec.fCloseTabNewCard)
        pobTran->srBRec.inType = shGetTranType(pobTran);

    /* If offline trans and, either not a close tab or close tab with diff card  */
    if ((pobTran->srBKey.fOffline == VS_TRUE) && ((!pobTran->srBRec.fCloseTabSameCard && !pobTran->srBRec.fCloseTabNewCard) || pobTran->srBRec.fCloseTabNewCard)) {

	 memset(pobTran->srBRec.szRespCode, ' ', RESP_CODE_SIZE);
        pobTran->srBRec.szRespCode[RESP_CODE_SIZE] = '\0';
        if (pobTran->srBRec.inType == CREDIT_TRAN && pobTran->srBKey.fOffline && strlen(pobTran->srBRec.szAuthCode) == 0) {
            memset(pobTran->srBRec.szAuthCode, ' ', AUTH_CODE_SIZE);
            pobTran->srBRec.szAuthCode[AUTH_CODE_SIZE] = '\0';
        }
    }

    strcpy(szPAN, pobTran->srBRec.szPAN);


    pobTran->srBKey.inBatchHostIndex = inGetBatchIndex();
    /* ( This variable has been set since the beggining. Also, it should not be HDTBatchIndex */

    pobTran->srBKey.fVoided = VS_FALSE;
    /* Set Uploaded Flag */
    if (pobTran->srBKey.fOffline == VS_TRUE)
        pobTran->srBKey.fUploaded = VS_FALSE;
    else
        pobTran->srBKey.fUploaded = VS_TRUE;

    /* Increment BDT Offline Count  */
    if (pobTran->srBKey.fOffline == VS_TRUE)
        inIncOfflineCount();



    /*  pobTran->srBRec.inNumberOfAdjusts = 0;
        pobTran->srBRec.inNumberOfTipAdjusts = 0;
        This was removed for the double link logic */

#if 1 /* KV1 Debug code for adding multiple transactions to the batch. */
     {
        int inNumRecs = 1,
        inCount = 0;
        char szBuf[10],
        szDisplay[30];
        long lnAvailSz;

        memset(szBuf, 0x00, sizeof(szBuf));
        memset(szDisplay, 0x00, sizeof(szDisplay));
        if (get_env("BRS", szBuf, 3) > 0 && fGetDemoMode())
            inNumRecs = str2int(szBuf);
        if (inNumRecs < 0 || inNumRecs> 999)
            inNumRecs = 1;
        if (inNumRecs > 1) {
            strcpy(szDisplay, "Adding records...");
            vdDisplayStatusString(szDisplay);
            pause(50);
            //get_char ();
        }
        do {

            ++inCount;
            inResult = inAddBatchRec(pobTran, &pobTran->srBKey, &pobTran->srBRec, DB_APPEND);
            if (inResult != VS_SUCCESS || --inNumRecs <= 0 || !fMemAvail(&lnAvailSz))
                break;
            sprintf(szDisplay, "%d done, %d togo", inCount, inNumRecs);
            vdDisplayStatusString(szDisplay);
            pause(50);
            pobTran->srBKey.lnInvNum++;
            inIncInvNum();
        } while (VS_TRUE);

        if (inResult != VS_SUCCESS) {

            if (inCount > 1 && errno == ENOSPC)
                inResult = VS_SUCCESS;
        }
        if (inCount > 1) {
            int inTotRecs = inGetBatchRecCnt(&pobTran->dbBatch);

            sprintf(szDisplay, "%d Records Added.", inCount);
            vdDisplayStatusString(szDisplay);
            //get_char ();
            pause(100);
            sprintf(szDisplay, "Batch Count = %d.", inTotRecs);
            vdDisplayStatusString(szDisplay);
            //get_char ();
            pause(100);
        }
    }
#else
    inResult = inAddBatchRec(pobTran, &pobTran->srBKey, &pobTran->srBRec, DB_APPEND);
#endif

    return(inResult);
}

/*********************************************************************************************
* @func int | inGetBatchRec |
*
*       Read specific batch record from batch by record number.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm int     | inRecNum |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inGetBatchRec(TRANSACTION_OBJECT* pobTran,int inRecNum) {
    if (inReadBatchData(&pobTran->dbBatch, &pobTran->srBKey, &pobTran->srBRec, (long) inRecNum) != VS_SUCCESS) {

        vdSGErrorMessage(BATCH_ERR_MSG);
        return(VS_ERR);
    }
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inGetKeyBatchRec |
*
*       Retrieves record specific record from the batch based in search key
*       information.
*       NOTE:   The Open Tab batch is used if it is open, otherwise the
*               Data Capture batch is used.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm int     | inKey |
* @parm BATCH_KEY * | psrBatchKey |
* @parm long    | lnDBWhat |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inGetDCKeyBatchRec(TRANSACTION_OBJECT* pobTran,int inKey,BATCH_KEY* psrBatchKey,long lnDBWhat) {

    return (inGetLinkedKeyBatchRec(pobTran, inKey, psrBatchKey, lnDBWhat, &pobTran->dbBatch));
}

int inGetLinkedKeyBatchRec(TRANSACTION_OBJECT* pobTran,int inKey,BATCH_KEY* psrBatchKey,long lnDBWhat,DB_FILE* psrDBF) {
    int inResult;
    /** /pdebug(("---inGetLinkedBatchRec---"));*/
    /*  Retrieve a record from the batch with a specific key value */
    // 'Prev' Key support

    if (lnDBWhat == DB_PREVIOUS)
        for (; ;) {

            if ((inResult = inGetKeyBatchRec(pobTran, inKey, psrBatchKey, lnDBWhat, psrDBF)) != VS_SUCCESS) {
                break;  /*  Key value not found */
            }
            if ((inKey & KEY_ALL_RECS) || pobTran->srBRec.lnForwardLinkInvNum == 0L) {
                inResult = VS_SUCCESS;
                break;
            }
        }
    else
        for (; ; lnDBWhat = DB_NEXT) {

            if ((inResult = inGetKeyBatchRec(pobTran, inKey, psrBatchKey, lnDBWhat, psrDBF)) != VS_SUCCESS) {
                break;  /*  Key value not found */
            }
            if ((inKey & KEY_ALL_RECS) || pobTran->srBRec.lnForwardLinkInvNum == 0L) {
                inResult = VS_SUCCESS;
                break;
            }
        }
    return(inResult);
}

int inGetKeyBatchRec(TRANSACTION_OBJECT* pobTran,int inKey,BATCH_KEY* psrBatchKey,long lnDBWhat,DB_FILE* psrDBF) {
    long lnRecNum = 0L;
    long lnRetVal;
    int inRetVal = VS_ERR;
    BATCH_KEY* psrLocalBKey;
    BATCH_REC* psrLocalBRec;

    //pdebug(("--inGetKeyBatchRec--"));
    //pdebug(("pobTran->srBRec.pchHostData   = %lX", pobTran->srBRec.pchHostData));

    if (inGetLocalBatchStructures(&psrLocalBKey, &psrLocalBRec) != VS_SUCCESS)
        return VS_ERR;

    /*
     *      Load Search Key Structure
     */

    pobTran->srBSKey.inKeyIdx = inKey;
    memcpy(&pobTran->srBSKey.BKey, psrBatchKey, SIZE_BATCH_KEY);

    /*
     *      Return value 1 indicates record found and successful read.
     */


    if ((lnRetVal = lnBatchGetKey(psrDBF, psrLocalBKey, &pobTran->srBSKey, lnDBWhat, psrLocalBRec, &lnRecNum)) == 1L) {
        //pdebug (("lnBatchGetKey == 1L"));
        /*
         *      Move local copy of batch data into TRANSACTION OBJECT
         *
         *          NOTE: Host data flexi record must be maintained.
         */

        memcpy(&pobTran->srBKey, psrLocalBKey, sizeof(BATCH_KEY));
        if (pobTran->srBRec.pchHostData != psrLocalBRec->pchHostData)
            vdFree((char *) pobTran->srBRec.pchHostData);
        else {
            //pdebug(("NO FREE"));
        }

        memcpy(&pobTran->srBRec, psrLocalBRec, sizeof(BATCH_REC));
        vdFree((char *) psrLocalBKey);
        vdFree((char *) psrLocalBRec);

        inRetVal = inLoadCardCurrenyHostData(pobTran);
    } else if (lnRetVal == 0L) {

        //pdebug (("lnBatchGetKey == 0L"));
        inRetVal = VS_EOB;
        vdSGErrorMessage(REC_NOT_FOUND_ERR_MSG);
        vdFreeLocalBatchStructures(psrLocalBKey, psrLocalBRec);
    } else {

        //pdebug (("lnBatchGetKey == %ld",lnRetVal));
        vdFreeLocalBatchStructures(psrLocalBKey, psrLocalBRec);
    }

    //pdebug(("pobTran->srBRec.pchHostData   = %lX", pobTran->srBRec.pchHostData));
    //pdebug(("inGetKeyBatchRec==DONE"));
    return(inRetVal);
}

/*********************************************************************************************
* @func int | inLoadBatchRec |
*
*       Loads specific batch record from the Data Capture batch based on record
*       number.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm int     | inRecNum |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inLoadBatchRec(TRANSACTION_OBJECT* pobTran,int inRecNum) {
    if (inGetBatchRec(pobTran, inRecNum) != VS_SUCCESS) {

        vdSGErrorMessage(BATCH_ERR_MSG);
        return(VS_ERR);
    }

    if (inLoadCardCurrenyHostData(pobTran) != VS_SUCCESS)
        return(VS_ERR);

    pobTran->fLanguageOnSwipe = VS_TRUE;
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inLoadNextBatchRec |
*
*       Loads the next batch record from the Data Capture batch.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm long    | lnDBWhat |
*
* @rdesc Return values.
*
* @flag int    |    - VS_SUCCESS,
*                   - VS_ERR
*                   - VS_EOB
* @end
**********************************************************************************************/

int inLoadNextBatchRec(TRANSACTION_OBJECT* pobTran,long lnDBWhat) {
    int inRetVal;

    inRetVal = inGetDCKeyBatchRec(pobTran, KEY_HOST, &pobTran->srBKey, lnDBWhat);
    if (inRetVal == VS_EOB)
        vdSGErrorMessage(0L);



    return (inRetVal);
}

/*********************************************************************************************
* @func int | inGetDCInvBatchRec |
*
*       Loads a batch record based on invoice number from Data Capture batch
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm int    | inKey |
* @parm long    | lnDBWhat |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inGetDCInvBatchRec(TRANSACTION_OBJECT* pobTran,int inKey,long lnDBWhat) {
    return (inGetInvBatchRec(pobTran, inKey, lnDBWhat, &pobTran->dbBatch));
}

/*********************************************************************************************
* @func int | inGetInvBatchRec |
*
*       Loads a batch record based on invoice number.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
* @parm integer | inkey |
* @parm long    | lnDBWhat |
* @parm DBFILE  | psrDBF |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inGetInvBatchRec(TRANSACTION_OBJECT* pobTran,int inKey,long lnDBWhat,DB_FILE* psrDBF) {
    int inResult = VS_ERR;
    long lnRecNum = 0L;       /* Retrieve the first record        */
    int inOrgCode   ;       /* Original Transaction Code        */
    long lnOrgInvNum ;       /* Original Transaction Invoice #   */
    BATCH_KEY srLocalBKey;    /* Local copy of batch key          */

    /*unsigned   fOrgManual ;    Original Manual/Swipe  flag        */
    /* We can't use this logic since retrieving a transaction is never swipe in SP2000.*/

    /** /pdebug(("---inGetInvBatch---"));*/

    if (lnDBWhat == DB_FIRST && pobTran->srBKey.lnInvNum > 0L) {
        /*
            1)  Retrieve the record in the batch with a specific invoice # if the record found
                doesn't belongs to a linked list or inKey = KEY_ALL_RECS
            2)  Retrieve the last record in the chain if the record found belongs to a linked list
                and inKey = KEY_INV_NUM
        */
        inOrgCode = pobTran->srBRec.inCode  ;
        lnOrgInvNum = pobTran->srBKey.lnInvNum;
        /*fOrgManual = pobTran->srBRec.fManual ;*/

        for (inResult = VS_ERR; ; pobTran->srBKey.lnInvNum = pobTran->srBRec.lnForwardLinkInvNum) {
            // Changed DB_FIRST to DB_LAST for LAC
            if (inGetKeyBatchRec(pobTran, KEY_INV_NUM, &pobTran->srBKey, DB_LAST, psrDBF) != VS_SUCCESS) {
                break;  /*  Invoice # not found */
            }
            if ((inKey & KEY_ALL_RECS) || pobTran->srBRec.lnForwardLinkInvNum == 0L) {
                inResult = VS_SUCCESS;
                break;
            }
        }

        if (inResult != VS_SUCCESS) {
            vdSGErrorMessage(INVALID_INV_NUM_ERR_MSG);
            return(VS_ERR);
        }

        /* Put original values in current transaction parameters */
        pobTran->srBRec.inOrgCode = inOrgCode  ;
        pobTran->srBRec.lnOrgInvNum = lnOrgInvNum;
        /*pobTran->srBRec.fManual       =  fOrgManual;*/
    } else {
        VS_BOOL fTraversing = VS_FALSE;
        /*  1) Retrieve the first record in the batch if a specific invoice #
            is not provided (i.e. ENTER KEY only is pressed at the "Invoice
            Number:" prompt during batch review, etc.)
            2) Retrieve Next record in the batch after a specific record has
            been retrieved by invoice #.
        */
        /*
            Use the Open Tab batch if it is available, otherwise operate on the Primary Batch
        */
        psrDBF = pobTran->fOTBatchOpen ? &pobTran->dbOTBatch : &pobTran->dbBatch;

        // 'Prev' Key Support
        //lnRecNum = pobTran->srBKey.lnInvNum > 0L ? DB_FORWARD : 0L;
        if (pobTran->srBKey.lnInvNum > 0L) {
            if (lnDBWhat == DB_PREVIOUS)
                lnRecNum = DB_BACKWARD;
            else
                lnRecNum = DB_FORWARD;
            fTraversing = VS_TRUE;
            memcpy(&srLocalBKey, &pobTran->srBKey, SIZE_BATCH_KEY);
        } else
            lnRecNum = 0L;

        if (inReadBatchData(psrDBF, &pobTran->srBKey, &pobTran->srBRec, lnRecNum) < 0) {
            vdSGErrorMessage(INVALID_INV_NUM_ERR_MSG);
            return(VS_ERR);
        }
        if (fTraversing && pobTran->srBKey.lnInvNum == srLocalBKey.lnInvNum) {
            if (inReadBatchData(psrDBF, &pobTran->srBKey, &pobTran->srBRec, lnRecNum) < 0) {
                vdSGErrorMessage(INVALID_INV_NUM_ERR_MSG);
                return(VS_ERR);
            }
        }
        if (inLoadCardCurrenyHostData(pobTran) != VS_SUCCESS)
            return(VS_ERR);
    }
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inVoidBatchRec |
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc Return values.
*
* @flag int    |    - VS_SUCCESS
* @end
**********************************************************************************************/

int inVoidBatchRec(TRANSACTION_OBJECT* pobTran) {
    TRANSACTION_OBJECT obTran;

    /** /pdebug(("--inVoidBatchRec--"));*/
    pobTran->fVoidedBatchRec = VS_TRUE;

    /* Load TRT locally for batch record    */
    inLoadTRTRec(&obTran, pobTran->srBRec.inCode);
    vdSetOffline(pobTran, obTran.srTRTRec.VoidOffline);
    vdSetPrintReceipt(pobTran, obTran.srTRTRec.VoidReceipt);
    vdSetDataCapture(pobTran, obTran.srTRTRec.DataCapture);

    /** /pdebug(("fVoided=%02x %02x",pobTran->srBKey.fVoided,obTran.srTRTRec.VoidAllowed));*/

    vdDisplayTranTitle(VOID_TRT_MSG);

    /* turned tip and tax print option on if amount > 0 */
    if (pobTran->srBRec.lnTipAmount)
        pobTran->srBRec.fTipEntered = VS_TRUE;

    if (pobTran->srBRec.lnTaxAmount)
        pobTran->srBRec.fTaxEntered = VS_TRUE;

    /* Decrement BDT Offline Count  */
    if (pobTran->srBKey.fOffline == VS_TRUE)
        inDecOfflineCount();

    /*
     *      Functionality previously performed in inModifyBatchRec ()
     */
    pobTran->srBKey.fVoided = VS_TRUE;

    inInitPrintOption(pobTran);

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inAdjustBatchRec |
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc Return values.
*
* @flag int    |    - VS_SUCCESS
* @end
**********************************************************************************************/

int inAdjustBatchRec(TRANSACTION_OBJECT* pobTran) {
    TRANSACTION_OBJECT obTran;

    /** /pdebug(("--inAdjustBatchRec--"));*/
    pobTran->fAdjustedBatchRec = VS_TRUE;

    /* Load TRT locally for batch record    */
    inLoadTRTRec(&obTran, pobTran->srBRec.inCode);

    /* Check batch record TRT   */
    vdSetOffline(pobTran, obTran.srTRTRec.AdjustOffline);
    vdSetPrintReceipt(pobTran, obTran.srTRTRec.AdjustReceipt);
    vdSetDataCapture(pobTran, obTran.srTRTRec.DataCapture);

    /*
     *      Functionality previously performed in inModifyBatchRec ()
     */
    pobTran->srBKey.fUploaded = VS_FALSE;  /* Reset the uploaded flag */
    if (pobTran->fTipAdjust) {
        pobTran->srBRec.fTipEntered = VS_TRUE;
        pobTran->srBRec.inNumberOfTipAdjusts++;
    } else if (pobTran->fAdjust)
        pobTran->srBRec.inNumberOfAdjusts++;

    inInitPrintOption(pobTran);

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func void | vdUndoAdjustBatchRec |
*
*       This reverses the adjust process in case of online failures.
*       Only undoes stuff that will affect the batch review display.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc VOID
* @end
**********************************************************************************************/

void vdUndoAdjustBatchRec(TRANSACTION_OBJECT* pobTran) {
    if (pobTran->fAdjustedBatchRec != VS_TRUE)
        return;

    pobTran->srBKey.lnTotalOfTransactionAmount = pobTran->srBRec.lnOldTotalTransactionAmount;
    pobTran->srBRec.lnTipAmount = pobTran->srBRec.lnOldTipAmount;
    pobTran->srBRec.lnTaxAmount = pobTran->lnOldTaxAmount;
    if (pobTran->fTipAdjust) {
        pobTran->srBRec.fTipEntered = VS_TRUE;
        pobTran->srBRec.inNumberOfTipAdjusts--;
    } else
        pobTran->srBRec.inNumberOfAdjusts--;

    pobTran->fAdjustedBatchRec = VS_FALSE;
}

/*********************************************************************************************
* @func void | vdUndoAdjustBatchRec |
*       This reverses the adjust process in case of online failures.
*       Only undoes stuff that will affect the batch review display.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc VOID
* @end
**********************************************************************************************/

void vdUndoVoidBatchRec(TRANSACTION_OBJECT* pobTran) {
    if (pobTran->fVoidedBatchRec != VS_TRUE)
        return;

    if (pobTran->srBKey.fOffline == VS_TRUE)
        inIncOfflineCount();

    pobTran->srBKey.fVoided = VS_FALSE;
    pobTran->fVoidedBatchRec = VS_FALSE;
}

/*********************************************************************************************
* @func int | inUpdateBatchFlow |
*
*       This routine updates the batch if necessary.  It is intended to be used from the TRT.
*
* @parm TRANSACTION_OBJECT * | pobTran |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inUpdateBatchFlow(TRANSACTION_OBJECT* pobTran) {
    /** /pdebug(("--inUpdateBatchFlow--"));*/



    if (!fGetDataCapture(pobTran))
        return(VS_SUCCESS);

    /* Update the PFR state, store transient data */
    inPFRStateStoreAll(PFR_BEGIN_BATCH_UPDATE, pobTran, 1, 1);

    if (inUpdateBatch(pobTran)) {

        /* Update the PFR state, store transient data */
        inPFRStateStoreAll(PFR_BATCH_UPDATE_COMPLETE, pobTran, 1, 1);
		if (pobTran->srTRTRec.TransactionCode == SALE){ 
			inRunFunction(pobTran, RENAME_REVERSAL_FILE);
		}
        return(VS_ERR);
    }


    /* Update the PFR state, store transient data */
    inPFRStateStoreAll(PFR_BATCH_UPDATE_COMPLETE, pobTran, 1, 1);
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inUpdateBatch |
*
*           For Adjusts and Voids update the batch record,
*           For Close Tabs
*               Transfer the transaction record from the Pre-Auth
*               batch to the regular batch
*           Otherwise, add transaction to batch
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/


/*
 *      Handle Batch Updates for Void and Adjusts
 *          - VS_SUCCESS,   Processing complete
 *          - VS_ERR,       Error abort transaction
 *          - VS_TRUE,      Continue processing
 */

int inDefaultIsVoidTransaction(TRANSACTION_OBJECT* pobTran) {
    if (shGetTransactionCode(pobTran) == VOID)
        return (VS_TRUE);
    else
        return (VS_FALSE);
}

int inImamModifyCurrentBatchRec(TRANSACTION_OBJECT* pobTran) 
{
    int inRetVal = VS_SUCCESS;
    long lnRecNum;
    BATCH_KEY* psrOrgBKey, * psrNewBKey;
    BATCH_REC* psrOrgBRec, * psrNewBRec;

    psrNewBKey = &pobTran->srBKey;
    psrNewBRec = &pobTran->srBRec;

    if (inGetLocalBatchStructures(&psrOrgBKey, &psrOrgBRec) != VS_SUCCESS)
        return VS_ERR;

    pobTran->srBSKey.inKeyIdx = KEY_INV_NUM;
    pobTran->srBSKey.BKey.lnInvNum = psrNewBRec->lnOrgInvNum;

    for (; ;) {
        if (lnBatchGetKey(&pobTran->dbBatch, psrOrgBKey, &pobTran->srBSKey, DB_FIRST, psrOrgBRec, &lnRecNum) != 1L) {
            inRetVal = VS_ERR;
            break;
            //          return VS_ERR;
        }
        if (psrOrgBRec->lnForwardLinkInvNum == 0L)
            break;
        else
            pobTran->srBSKey.BKey.lnInvNum = psrOrgBRec->lnForwardLinkInvNum;
    }
    //pdebug (("fUploaded set"));
    if (inRetVal == VS_SUCCESS) {
		if (inAddBatchRec(pobTran, psrNewBKey, psrNewBRec, DB_CURRENT) != VS_SUCCESS)
			inRetVal = VS_ERR;
    }
    vdFreeLocalBatchStructures(psrOrgBKey, psrOrgBRec);
    return(inRetVal);
}

int inUpdateBatchForVoid(TRANSACTION_OBJECT* pobTran) {
    return(inRunFunction(pobTran, UPDATE_BATCH_FOR_VOID));
}

int inDefaultUpdateBatchForVoid(TRANSACTION_OBJECT* pobTran) {
    int inRetVal = VS_SUCCESS;
    long lnRecNum;
    BATCH_KEY* psrOrgBKey,
    * psrNewBKey;
    BATCH_REC* psrOrgBRec,
    * psrNewBRec;

    //pdebug (("--inDefaultUpdateBatchForVoid--"));

    psrNewBKey = &pobTran->srBKey;
    psrNewBRec = &pobTran->srBRec;

    if (inGetLocalBatchStructures(&psrOrgBKey, &psrOrgBRec) != VS_SUCCESS)
        return VS_ERR;

    pobTran->srBSKey.inKeyIdx = KEY_INV_NUM;
    pobTran->srBSKey.BKey.lnInvNum = psrNewBRec->lnOrgInvNum;

    for (; ;) {
        if (lnBatchGetKey(&pobTran->dbBatch, psrOrgBKey, &pobTran->srBSKey, DB_FIRST, psrOrgBRec, &lnRecNum) != 1L) {
            inRetVal = VS_ERR;
            break;
            //          return VS_ERR;
        }
        if (psrOrgBRec->lnForwardLinkInvNum == 0L)
            break;
        else
            pobTran->srBSKey.BKey.lnInvNum = psrOrgBRec->lnForwardLinkInvNum;
    }

    //pdebug (("Got LocalBatchStructures"));
    if (inRetVal == VS_SUCCESS) {
        if (psrNewBKey->fOffline)   /* Void Offline */ {
            if (psrOrgBKey->fOffline)   /* Original Tx was done offline */ {
                if (psrOrgBKey->fUploaded)  /* Original Tx was uploaded */ {
                    psrNewBKey->fUploaded = VS_FALSE;   /* Void will be uploaded later */
                } else {
                    if (fGetDoNotUploadOfflinePairTransVoid()) {
                        /* Void will be never be uploaded */
                        /* Host won't know about original or void */

                        //psrNewBKey->fUploaded = VS_TRUE; Changed for LAC
                        psrOrgBKey->fUploaded = VS_TRUE;

                        /* Both transactions won't be uploaded during Batch Upload */

                        psrOrgBRec->fDoNotUploadRec = VS_TRUE;
                        psrNewBRec->fDoNotUploadRec = VS_TRUE;
                    } else
                        psrNewBKey->fUploaded = VS_FALSE;
                }
            } else  /* Original Tx was done online */ {
                psrNewBKey->fUploaded = VS_FALSE;   /* Void will be uploaded later */
            }
        } else  /* Void Online */
            psrNewBKey->fUploaded = VS_TRUE;

        psrOrgBKey->fVoided = VS_TRUE;

        switch (chGetBatchUploadSchemeForVoid()) {
        case UPLOAD_NONE :
            psrOrgBRec->fDoNotUploadRec = VS_TRUE;
            psrNewBRec->fDoNotUploadRec = VS_TRUE;
            break;
        case UPLOAD_LAST :
            psrOrgBRec->fDoNotUploadRec = VS_TRUE;
            break;
        case UPLOAD_ALL :
            /* Default is upload all */
            break;
        default :
            vdSGErrorMessage(INVALID_UPLOAD_SCHEME_MSG);
            inRetVal = VS_ERR;
            //                              return(VS_ERR);
            break;
        }
    }

    //pdebug (("fUploaded set"));
    if (inRetVal == VS_SUCCESS) {
        psrNewBRec->fLastTranUploaded = (psrOrgBKey->fUploaded || !psrOrgBKey->fOffline);

        if (fGetAllTransAsANewRegisterInBatch()) {
            //pdebug (("fGetBDTAllTransAsANewRegisterInBatch"));
            psrOrgBRec->lnForwardLinkInvNum = psrNewBKey->lnInvNum;

            /* Save over existing register */
            if (inAddBatchRec(pobTran, psrOrgBKey, psrOrgBRec, DB_CURRENT) == VS_SUCCESS) {
                psrNewBRec->lnBackLinkInvNum = psrOrgBKey->lnInvNum;
                psrNewBRec->lnForwardLinkInvNum = 0;

                /* Save current transaction data as new register in Batch */
                if (inAddBatchRec(pobTran, psrNewBKey, psrNewBRec, DB_APPEND) != VS_SUCCESS)
                    inRetVal = VS_ERR;
            } else
                inRetVal = VS_ERR;
        } else {
            //pdebug (("Update RegisterInBatch"));
            if (inAddBatchRec(pobTran, psrNewBKey, psrNewBRec, DB_CURRENT) != VS_SUCCESS)
                inRetVal = VS_ERR;
        }
    }

    //pdebug (("pre-vdFreeLocalBatchStructures"));
    vdFreeLocalBatchStructures(psrOrgBKey, psrOrgBRec);
    //pdebug (("inDefaultUpdateBatchForVoid=DONE"));
    return(inRetVal);
}

int inUpdateBatchForAdjust(TRANSACTION_OBJECT* pobTran) {
    return(inRunFunction(pobTran, UPDATE_BATCH_FOR_ADJUST));
}

int inDefaultUpdateBatchForAdjust(TRANSACTION_OBJECT* pobTran) {
    int inRetVal = VS_SUCCESS;
    long lnRecNum;
    BATCH_KEY* psrOrgBKey,
    * psrNewBKey;
    BATCH_REC* psrOrgBRec,
    * psrNewBRec;

    psrNewBKey = &pobTran->srBKey;
    psrNewBRec = &pobTran->srBRec;

    if (inGetLocalBatchStructures(&psrOrgBKey, &psrOrgBRec) != VS_SUCCESS)
        return VS_ERR;

    pobTran->srBSKey.inKeyIdx = KEY_INV_NUM;
    pobTran->srBSKey.BKey.lnInvNum = psrNewBRec->lnOrgInvNum;

    for (; ;) {
        if (lnBatchGetKey(&pobTran->dbBatch, psrOrgBKey, &pobTran->srBSKey, DB_FIRST, psrOrgBRec, &lnRecNum) != 1L) {
            inRetVal = VS_ERR;
            break;
            //          return VS_ERR;
        }
        if (psrOrgBRec->lnForwardLinkInvNum == 0L)
            break;
        else
            pobTran->srBSKey.BKey.lnInvNum = psrOrgBRec->lnForwardLinkInvNum;
    }

    if (inRetVal == VS_SUCCESS) {
        if (psrNewBKey->fOffline)   /* Adjust Offline */ {
            if (psrOrgBKey->fOffline)   /* Original Tx was done offline */ {
                if (psrOrgBKey->fUploaded)          /* Original Tx was uploaded */ {
                    psrNewBKey->fUploaded = VS_FALSE;   /* Adjust will be uploaded later */
                } else {
                    /* This code should never be executed since Adjusts of "Offlines not uploaded"
                                   are not permited
                                */
                    psrNewBKey->fUploaded = VS_FALSE;   /* Adjust will be uploaded later */
                }
            } else  /* Original Tx was done online */ {
                psrNewBKey->fUploaded = VS_FALSE;   /* Adjust will be uploaded later */
            }
        } else  /* Adjust Online */ {
            if (psrOrgBKey->fOffline)   /* Original Tx was done offline */ {
                if (!psrOrgBKey->fUploaded) /* Original Tx was not uploaded */ {
                    /* This code should never be executed since Adjusts of "Offlines not uploaded" are not permited */
                    psrOrgBKey->fUploaded = VS_TRUE;
                }
            }
        }

        /* Adjust flags are not inside BATCH_REC. How to set as SP3.0 ??? */

        switch (chGetBatchUploadSchemeForAdjust()) {
        case UPLOAD_NONE :
            psrOrgBRec->fDoNotUploadRec = VS_TRUE;
            psrNewBRec->fDoNotUploadRec = VS_TRUE;
            break;
        case UPLOAD_LAST :
            psrOrgBRec->fDoNotUploadRec = VS_TRUE;
            break;
        case UPLOAD_ALL :
            /* Default is upload all */
            break;
        default :
            vdSGErrorMessage(INVALID_UPLOAD_SCHEME_MSG);
            return(VS_ERR);
            // break;
        }
    }

    if (inRetVal == VS_SUCCESS) {
        psrNewBRec->fLastTranUploaded = (psrOrgBKey->fUploaded || !psrOrgBKey->fOffline);

        if (fGetAllTransAsANewRegisterInBatch() && (fGetTipAsANewRegisterInBatch() && pobTran->fTipAdjust)) {
            psrOrgBRec->lnForwardLinkInvNum = psrNewBKey->lnInvNum;

            /* Save over existing register */
            if (inAddBatchRec(pobTran, psrOrgBKey, psrOrgBRec, DB_CURRENT) == VS_SUCCESS) {
                psrNewBRec->lnBackLinkInvNum = psrOrgBKey->lnInvNum;
                psrNewBRec->lnForwardLinkInvNum = 0;

                /* Save current transaction data as new register in Batch */
                if (inAddBatchRec(pobTran, psrNewBKey, psrNewBRec, DB_APPEND) != VS_SUCCESS) {
                    inRetVal = VS_ERR;
                    //                  return(VS_ERR);
                }
            } else {
                inRetVal = VS_ERR;
                //              return(VS_ERR);
            }
        } else {
            if (inAddBatchRec(pobTran, psrNewBKey, psrNewBRec, DB_CURRENT) != VS_SUCCESS) {
                inRetVal = VS_ERR;
                //               return(VS_ERR);
            }
        }
    }

    vdFreeLocalBatchStructures(psrOrgBKey, psrOrgBRec);
    return(inRetVal);
}


int inUpdateBatchForVoidAndAdjust(TRANSACTION_OBJECT* pobTran) {
    return(inRunFunction(pobTran, UPDATE_BATCH_FOR_VOID_AND_ADJUST));
}

int inDefaultUpdateBatchForVoidAndAdjust(TRANSACTION_OBJECT* pobTran) {
    int inResult;

    //pdebug (("--inDefaultUpdateBatchForVoidAndAdjust--"));

    if (pobTran->fVoidedBatchRec) {
        if ((inResult = inUpdateBatchForVoid(pobTran)) <= VS_SUCCESS)
            return(inResult);
    } else if (pobTran->fAdjust || pobTran->fTipAdjust || pobTran->fOtherAdjust || pobTran->fTaxAdjust) {
        if ((inResult = inUpdateBatchForAdjust(pobTran)) <= VS_SUCCESS)
            return(inResult);
    }
    return VS_TRUE; /*  Let "inUpdateBatch" add the new batch record */
}

int inUpdateBatch(TRANSACTION_OBJECT* pobTran) {
    int inRetVal;



    //pdebug (("--inUpdateBatch--"));

    /* Handle Batch Updates for Void and Adjusts */
    /* Return VS_TRUE to add new batch record if necessary */
    if ((inRetVal = inUpdateBatchForVoidAndAdjust(pobTran)) <= VS_SUCCESS)
    	{

        return inRetVal;
    	}
    /*
        *      For Close Tabs
        *          Transfer the transaction record from the Pre-Auth
        *          batch to the regular batch
        */
    if (pobTran->srBRec.fCloseTabSameCard || pobTran->srBRec.fCloseTabNewCard) {
        pobTran->srBRec.lnMessage = PRE_COMP_MSG;
        if (inPutPreAuthBatRec(pobTran) != VS_SUCCESS)
            return(VS_ERR);
        vdSGCode(PRE_COMP);
        return(VS_SUCCESS);
    }

    if (inPutBatchRec(pobTran) != VS_SUCCESS)
        return(VS_ERR);
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inGetHostTranCnt |
*
*       Uses Accum to compute host transaction count.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc Return values.
*
* @flag int    |    - Transaction Count
*                   - VS_ERR
* @end
**********************************************************************************************/

int inGetHostTranCnt(TRANSACTION_OBJECT* pobTran) {
    long lnCount;

    ACCUM_REC srHostTotals;

    /** /pdebug (("--inGetHostTranCnt--"));*/

    if (inGetHostTotals(pobTran, &srHostTotals) != VS_SUCCESS)
        return (VS_ERR);

    /* total transaction count*/
    lnCount = srHostTotals.srTotals[DEBIT_CARD].lnCount[DEBIT_TRAN] + srHostTotals.srTotals[DEBIT_CARD].lnCount[CREDIT_TRAN] + srHostTotals.srTotals[CREDIT_CARD].lnCount[DEBIT_TRAN] + srHostTotals.srTotals[CREDIT_CARD].lnCount[CREDIT_TRAN] + srHostTotals.srTotals[DEBIT_CARD].lnCount[VOID_REFUND_TRAN] + srHostTotals.srTotals[DEBIT_CARD].lnCount[VOID_SALE_TRAN] + srHostTotals.srTotals[CREDIT_CARD].lnCount[VOID_REFUND_TRAN] + srHostTotals.srTotals[CREDIT_CARD].lnCount[VOID_SALE_TRAN];


    return((int) lnCount);
}

/*********************************************************************************************
* @func int | inInitPurgeHostFromBatch |
*
*       Completes deleting batch records for a particular host if power fail
*       occurred during initial purge. Called during application init.
*
* @parm TRANSACTION_OBJECT *    | pobTran |
*
* @rdesc Return values.
*
* @flag int    |    - VS_SUCCESS
* @end
**********************************************************************************************/

int inInitPurgeHostFromBatch(TRANSACTION_OBJECT* pobTran) {
    long lnDBWhat,
    lnRecNum,
    lnRetVal;
    BATCH_KEY* psrLocalBKey;
    BATCH_SKEY srBSKey;
    BATCH_REC* psrLocalBRec;
    char szPFDHST[MAX_CONFIG_NM_SIZE + 1];
    char szConfigData[ENV_BUF_SIZE];
    int inHostNum;

    /** /pdebug (("--inInitPurgeHostFromBatch--"));*/

    /* if power fail occurred during initial batch purge, complete purge */
    vdGetMessageFromFile(PFDHST_ENVVAR, szPFDHST);
    MEMCLR(szConfigData, 0);
    if (get_env(szPFDHST, szConfigData, 2) > 0) {
        if (inGetLocalBatchStructures(&psrLocalBKey, &psrLocalBRec) != VS_SUCCESS)
            return VS_ERR;
        inHostNum = str2int(szConfigData);

        vdDisplayMessageFromFile(DELETING_BATCH_MSG21, STATUS_MSG);

        vdBatchDCOpen(pobTran);
        srBSKey.compare_func = (PFI) inCompareFn; /*inCompFn;*/
        srBSKey.inKeyIdx = KEY_HOST;
        srBSKey.BKey.inBatchHostIndex = inHostNum;

        /*
         *      Locate all records matching inHostNum and delete them
         */
        lnDBWhat = DB_LAST;
        do {
            if ((lnRetVal = lnBatchGetKey(&pobTran->dbBatch, psrLocalBKey, &srBSKey, lnDBWhat, psrLocalBRec, &lnRecNum)) == 1L)
                lnRetVal = db_delete(&pobTran->dbBatch, lnRecNum, 1L);
            lnDBWhat = DB_BACKWARD;
        } while (lnRetVal > 0L);

        inLoadMHTRec(inHostNum);
        vdSetMustClear(VS_FALSE);
        vdSetMustSettleFlag(VS_FALSE);
        inSaveMHTRec(inHostNum);  /* Disk write */

        /* put_env (szPFDHST, NULL_S, 0); */
        put_env(szPFDHST, "", 0);

        vdFreeLocalBatchStructures(psrLocalBKey, psrLocalBRec);

        /* Remove the reversal and offline files if exist */
        vdReversalsDelete(inHostNum);
    } /* end if powerfailed during purge batch */

    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inInitBatchFlexiRec |
*
*       Creates the flexi record for the batch record
*
* @parm BATCH_KEY * | psrBKey |
*       Batch Key structure pointer
*
* @parm BATCH_REC * | psrBRec |
*       Batch Data structure pointer
*
* @rdesc Return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inInitBatchStructures(BATCH_KEY* psrBKey,BATCH_REC* psrBRec) {
    memset(psrBKey, 0, SIZE_BATCH_KEY);
    memset(psrBRec, 0, SIZE_BATCH_REC);

    if ((psrBRec->pchHostData = (unsigned char *) pchAlloc(MAX_HOST_DATA_FLEXI_SZ)) == NULL_CH) {

        vdSGErrorMessage(NO_MEM_ERR_MSG);
        return (VS_ERR);
    }

    vVarInitRecord(psrBRec->pchHostData, MAX_HOST_DATA_FLEXI_SZ, 0);

    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inGetLocalBatchStructures |
*
*       Allocate space for batch key structure, record structure, and host data flexi record.
*       Clear and inititialize elements.
*
* @parm BATCH_KEY * | psrBKey |
*       Batch Key structure pointer
*
* @parm BATCH_REC * | psrBRec |
*       Batch Data structure pointer
*
* @rdesc return values.
*
* @flag int     |   - VS_SUCCESS
*                   - VS_ERR
* @end
**********************************************************************************************/

int inGetLocalBatchStructures(BATCH_KEY** psrBKey,BATCH_REC** psrBRec) {
    /*
     *      Allocate space for Key Structure
     */

     if ((*psrBKey = (BATCH_KEY *) pchAlloc(SIZE_BATCH_KEY)) == NULL_CH) {

        vdSGErrorMessage(NO_MEM_ERR_MSG);
        return VS_ERR;
    }
    /*
     *      Allocate space for Record Structure
     */
    if ((*psrBRec = (BATCH_REC *) pchAlloc(SIZE_BATCH_REC)) == NULL_CH) {

        vdFree((char *) *psrBKey);
        vdSGErrorMessage(NO_MEM_ERR_MSG);
        return VS_ERR;
    }
    /*
     *      Initialize Batch Structures and host flexi record.
     */
    if (inInitBatchStructures(*psrBKey, *psrBRec) != VS_SUCCESS) {

        vdFree((char *) *psrBRec);
        vdFree((char *) *psrBKey);
        return VS_ERR;
    }

    return VS_SUCCESS;
}

/*********************************************************************************************
* @func void | vdFreeLocalBatchStructures |
*
*       Free space used by batch key structure, record structure, and host data flexi record.
*
* @parm BATCH_KEY * | psrBKey |
*       Batch Key structure pointer
*
* @parm BATCH_REC * | psrBRec |
*       Batch Data structure pointer
*
* @rdesc VOID.
* @end
**********************************************************************************************/

void vdFreeLocalBatchStructures(BATCH_KEY* psrBKey,BATCH_REC* psrBRec) {
    vdFree((char *) psrBRec->pchHostData);
    vdFree((char *) psrBRec);
    vdFree((char *) psrBKey);
    psrBRec->pchHostData = NULL;
}

/*********************************************************************************************
* @func int | lnBatchGetKey |
*
*       Replaces data base functionality previously performed by db_get_key(). Required due to
*       the variable nature of the data portion of the batch record with flexi record support.
*
* @parm DB_FILE * | psrDBF |
*       Data base file pointer
*
* @parm BATCH_KEY * | psrBKey |
*       Batch Key structure pointer
*
* @parm BATCH_SKEY * | psrBSKey |
*       Batch Search Key structure pointer
*
* @parm long  | lnDBWhat |
*       Data base action indicator
*
* @parm BATCH_REC * | psrBRec |
*       Batch Data structure pointer
*
* @parm long * | plnRecNum |
*       plnRecNum
*
* @rdesc return values.
*
* @flag int     |   - 1, Requested number of occurrences was found
*                   - 0, No key was found or the requested number of occurrences was not found
*                   - (-1), SYSTEM_ERROR (global variable errno contains the error code)
* @end
**********************************************************************************************/

long lnBatchGetKey(DB_FILE* psrDBF,BATCH_KEY* psrBKey,BATCH_SKEY* psrBSKey,long lnDBWhat,BATCH_REC* psrBRec,long* plnRecNum) {
    long lnRetVal;

    //pdebug (("--lnBatchGetKey--"));

    lnRetVal = db_seek_key(psrDBF, psrBKey, psrBSKey, lnDBWhat, plnRecNum);
    // 'Prev' Key support
    if (lnRetVal > 0L)
        lnRetVal = db_seek_key(psrDBF, psrBKey, psrBSKey, lnDBWhat, plnRecNum);
    if (lnRetVal > 0L) {

        if (inReadBatchData(psrDBF, psrBKey, psrBRec, *plnRecNum) != VS_SUCCESS)
        {

            lnRetVal = (long) VS_ERR;
	}
    }

    return lnRetVal;
}

/*********************************************************************************************
* @func int | inReadReprintBatchData |
*
*       Read Reprint Batch data record from reprint file.
*       Extract data to Batch structure and flexi record.
*
* @parm BATCH_KEY * | psrBKey |
*       Batch Key structure pointer
*
* @parm BATCH_REC * | psrBRec |
*       Batch Data structure pointer
*
* @parm DB_FILE * | psrDBF |
*       Data base file pointer
*
* @parm long | lnRecNum |
*       lnRecNum
*
* @rdesc return values.
*
* @flag int    |    - VS_ERR
*                   - Size of batch data record.
* @end
**********************************************************************************************/
int inReadReprintBatchData(DB_FILE* psrDBF,BATCH_KEY* psrBKey,BATCH_REC* psrBRec,long lnRecNum) {
    int inRetVal = VS_SUCCESS /*,inBatchRecFlexiSz*/;
    //jrd one source
    #ifdef __arm
    short shBatchRecFlexiSz;
    #endif  /* __arm  */
    #ifdef _TARG_68000
    int shBatchRecFlexiSz;
    #endif  /* _TARG_68000  */

    short shMaxBatchDataSz;
    unsigned char * pchTempBatchData;
    short shRet;

    // We need to get the maximum size that a record can be because we can't
    // use inGetMaxBatchRecSize() because we don't have the merchant # and
    // batch file loaded at the time of reprint last
    shMaxBatchDataSz = MAX_HOST_DATA_FLEXI_SZ + SIZE_BATCH_DATA + SIZE_OPTIONAL_BATCH_REC;

    //pdebug (("--inReadReprintBatchData--"));

    // Allocate space for fixed and flexi portion of batch data.
    if ((pchTempBatchData = (unsigned char *) pchAlloc(shMaxBatchDataSz)) == NULL_CH)
        inRetVal = VS_ERR;

    // Read batch record
    if (inRetVal == VS_SUCCESS) {
        if (db_read(psrDBF, psrBKey, (char *) pchTempBatchData, shMaxBatchDataSz, lnRecNum) < 0)
            inRetVal = VS_ERR;
        else {
            //Free current batch flexi record
            vdFree((char *) psrBRec->pchHostData);
        }
    }

    // move batch data structure
    if (inRetVal == VS_SUCCESS) {
        memcpy(psrBRec, pchTempBatchData, SIZE_BATCH_DATA);
        if (inLoadOptionalBatchRecFromFlexi(pchTempBatchData + SIZE_BATCH_DATA, psrBRec) != VS_SUCCESS)
            inRetVal = VS_ERR;
    }

    // Copy new batch flexi record
    if (inRetVal == VS_SUCCESS) {
        if ((psrBRec->pchHostData = (unsigned char *) pchAlloc(MAX_HOST_DATA_FLEXI_SZ)) == NULL_CH)
            inRetVal = VS_ERR;
        else {
            if ((shRet = shGetRecordLength(pchTempBatchData + SIZE_BATCH_DATA, &shBatchRecFlexiSz)) != VAR_NO_ERROR)
                inRetVal = VS_ERR;
            else {
                vVarInitRecord(psrBRec->pchHostData, MAX_HOST_DATA_FLEXI_SZ, 0);
                if ((shRet = shVarFlatten(pchTempBatchData + SIZE_BATCH_DATA + shBatchRecFlexiSz, psrBRec->pchHostData)) != VAR_NO_ERROR)
                    inRetVal = VS_ERR;
            }
        } /* end else Host Flexi alloc successful */
    } /* end if retval == VS_SUCCESS */

    if (pchTempBatchData != NULL) {
        //pdebug(("vdFree (%lX)", pchTempBatchData));
        vdFree((char *) pchTempBatchData);
    }

    if (inRetVal != VS_SUCCESS)
    {

        vdSGErrorMessage(BATCH_ERR_MSG);
	}
    return  inRetVal;
}

int BATCH_CODE_CHECK(char* a,char* b,short * c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);
    return 1;
}

#undef VSBATCH_C

#endif // BATCH_DEFINED
